import sys
import sqlite3
import os
import re
import shutil

from PySide6.QtCore import QSettings, QEvent, QSize, Qt
from PySide6.QtGui import QFont, QPixmap, QIcon
from PySide6.QtWidgets import (
    QMainWindow,
    QWidget,
    QVBoxLayout,
    QHBoxLayout,
    QPushButton,
    QStackedWidget,
    QLabel,
    QLineEdit,
    QTableWidget,
    QMessageBox,
    QFileDialog,
    QTableWidgetItem,
    QHeaderView,
    QGroupBox,
    QFormLayout,
    QComboBox,
    QListWidget,
    QListWidgetItem,
    QCheckBox,
    QApplication,
)


class MedicineImageManager(QMainWindow):
    def __init__(self):
        super().__init__()
        # 初始化设置
        self.init_settings()
        # 初始化UI
        self.initUI()
        # 初始化图片列表
        self.images = []
        self.main_image_index = -1

    def init_settings(self):
        """初始化设置"""
        self.settings = QSettings('MedicineManager', 'MedicineImageManager')
        # 获取保存路径，如果不存在则使用默认路径
        self.save_path = self.settings.value(
            'save_path', r'\\192.168.0.37\药品图片数据库'
        )

    def initUI(self):
        # 设置窗口标题和大小
        self.setWindowTitle('药品图片管理系统')
        self.setFixedSize(1440, 880)

        # 窗口居中显示（使用现代API）
        frame_gm = self.frameGeometry()
        center_point = self.screen().availableGeometry().center()
        frame_gm.moveCenter(center_point)
        self.move(frame_gm.topLeft())

        # 创建主Widget和布局
        central_widget = QWidget()
        self.setCentralWidget(central_widget)
        main_layout = QVBoxLayout(central_widget)
        main_layout.setContentsMargins(0, 0, 0, 0)
        main_layout.setSpacing(0)

        # 创建导航栏
        nav_bar = QWidget()
        nav_bar.setStyleSheet("background-color: #3498db;")
        nav_bar.setFixedHeight(60)
        nav_layout = QHBoxLayout(nav_bar)
        nav_layout.setContentsMargins(20, 0, 20, 0)

        # 创建导航按钮
        self.upload_btn = QPushButton('上传')
        self.manage_btn = QPushButton('管理')
        self.search_btn = QPushButton('搜索')
        self.settings_btn = QPushButton('设置')

        # 设置按钮样式
        button_style = """
            QPushButton {
                color: white;
                background-color: transparent;
                border: none;
                font-size: 16px;
                padding: 10px 20px;
                border-radius: 5px;
            }
            QPushButton:hover {
                background-color: rgba(255, 255, 255, 0.2);
            }
            QPushButton:pressed {
                background-color: rgba(255, 255, 255, 0.3);
            }
        """

        self.upload_btn.setStyleSheet(button_style)
        self.manage_btn.setStyleSheet(button_style)
        self.search_btn.setStyleSheet(button_style)
        self.settings_btn.setStyleSheet(button_style)

        # 添加按钮到导航栏
        nav_layout.addWidget(self.search_btn)
        nav_layout.addWidget(self.manage_btn)
        nav_layout.addWidget(self.upload_btn)
        nav_layout.addWidget(self.settings_btn)

        # 添加导航栏到主布局
        main_layout.addWidget(nav_bar)

        # 创建堆叠窗口用于管理不同页面
        self.stacked_widget = QStackedWidget()
        main_layout.addWidget(self.stacked_widget)

        # 创建页面
        self.upload_page = self.create_upload_page()
        self.manage_page = self.create_manage_page()
        self.search_page = self.create_search_page()
        self.settings_page = self.create_settings_page()

        # 添加页面到堆叠窗口
        self.stacked_widget.addWidget(self.upload_page)
        self.stacked_widget.addWidget(self.manage_page)
        self.stacked_widget.addWidget(self.search_page)
        self.stacked_widget.addWidget(self.settings_page)

        # 连接按钮信号和槽函数
        self.upload_btn.clicked.connect(self.on_upload_clicked)
        self.manage_btn.clicked.connect(
            lambda: self.stacked_widget.setCurrentWidget(self.manage_page)
        )
        self.search_btn.clicked.connect(
            lambda: self.stacked_widget.setCurrentWidget(self.search_page)
        )
        self.settings_btn.clicked.connect(
            lambda: self.stacked_widget.setCurrentWidget(self.settings_page)
        )

        # 设置默认显示搜索页面
        self.stacked_widget.setCurrentWidget(self.search_page)

    def on_upload_clicked(self):
        """上传页面点击事件，重置图片列表"""
        self.stacked_widget.setCurrentWidget(self.upload_page)
        self.images = []
        self.main_image_index = -1
        self.image_list.clear()

    def create_manage_page(self):
        """创建管理页面，包含表格和搜索框"""
        page = QWidget()
        layout = QVBoxLayout(page)
        layout.setContentsMargins(25, 25, 25, 25)
        layout.setSpacing(20)

        # 创建搜索区域
        search_layout = QHBoxLayout()
        search_label = QLabel("搜索:")
        search_label.setFont(QFont("Microsoft YaHei", 12))
        self.search_edit = QLineEdit()
        self.search_edit.setFont(QFont("Microsoft YaHei", 12))
        self.search_edit.setPlaceholderText("输入商品编码、通用名或生产厂家...")
        search_btn = QPushButton("搜索")
        search_btn.setFont(QFont("Microsoft YaHei", 12))
        search_btn.setFixedWidth(90)
        search_btn.setStyleSheet(
            "background-color: #3498db; color: white; padding: 5px 15px; border-radius: 5px;"
        )
        search_btn.clicked.connect(self.search_data)

        search_layout.addWidget(search_label)
        search_layout.addWidget(self.search_edit)
        search_layout.addWidget(search_btn)
        layout.addLayout(search_layout)

        # 创建表格
        self.table = QTableWidget()
        self.table.setFont(QFont("Microsoft YaHei", 12))
        # 设置表头
        headers = ["商品编码", "通用名", "规格", "生产厂家", "分类"]
        self.table.setColumnCount(len(headers))
        self.table.setHorizontalHeaderLabels(headers)
        # 设置表格样式
        self.table.horizontalHeader().setStyleSheet(
            "QHeaderView::section {background-color: #f0f0f0; font-weight: bold;}"
        )
        self.table.setAlternatingRowColors(True)
        self.table.setStyleSheet("alternate-background-color: #f9f9f9;")
        # 设置整行选择模式
        self.table.setSelectionBehavior(QTableWidget.SelectionBehavior.SelectRows)
        self.table.setSelectionMode(QTableWidget.SelectionMode.SingleSelection)

        # 设置双击单元格进入编辑状态
        self.table.setEditTriggers(QTableWidget.EditTrigger.DoubleClicked)

        # 设置选中行样式
        self.table.setStyleSheet(
            """
            alternate-background-color: #f9f9f9;
            QTableWidget::item:selected {
                background-color: #3498db;
                color: white;
            }
        """
        )

        # 连接单元格变化信号
        self.table.cellChanged.connect(self.on_cell_changed)

        # 为表格安装事件过滤器
        self.table.installEventFilter(self)

        # 设置最后一列拉伸到底部
        self.table.horizontalHeader().setStretchLastSection(True)

        layout.addWidget(self.table)

        # 添加图片显示区域
        image_container = QWidget()
        image_layout = QHBoxLayout(image_container)
        image_layout.setSpacing(10)

        # 创建6个图片标签、更换按钮、添加按钮和删除按钮（主图不添加添加和删除按钮）
        self.image_labels = []
        self.replace_buttons = []
        self.add_buttons = []
        self.delete_buttons = []
        for i in range(6):
            # 创建垂直布局包含图片和按钮
            v_layout = QVBoxLayout()
            v_layout.setSpacing(5)

            # 图片标签
            label = QLabel()
            label.setFixedSize(200, 200)
            label.setStyleSheet("border: 1px solid #ddd;")
            label.setAlignment(Qt.AlignmentFlag.AlignCenter)
            # 初始不设置tooltip，在on_table_row_clicked中动态设置
            label.setToolTip("")
            self.image_labels.append(label)
            v_layout.addWidget(label)

            # 按钮水平布局
            btn_layout = QHBoxLayout()
            btn_layout.setSpacing(5)

            # 更换按钮
            replace_btn = QPushButton("更换")
            replace_btn.setFixedWidth(60)
            replace_btn.setFont(QFont("Microsoft YaHei", 10))
            replace_btn.setStyleSheet(
                "background-color: #3498db; color: white; border-radius: 3px;"
            )
            replace_btn.clicked.connect(lambda checked, idx=i: self.replace_image(idx))
            self.replace_buttons.append(replace_btn)
            btn_layout.addWidget(replace_btn)

            # 添加按钮 (主图不添加添加按钮)
            if i != 0:
                add_btn = QPushButton("添加")
                add_btn.setFixedWidth(60)
                add_btn.setFont(QFont("Microsoft YaHei", 10))
                add_btn.setStyleSheet(
                    "background-color: #2ecc71; color: white; border-radius: 3px;"
                )
                add_btn.clicked.connect(lambda checked, idx=i: self.add_image(idx))
                self.add_buttons.append(add_btn)
                btn_layout.addWidget(add_btn)

            # 删除按钮 (主图不添加删除按钮)
            if i != 0:
                delete_btn = QPushButton("删除")
                delete_btn.setFixedWidth(60)
                delete_btn.setFont(QFont("Microsoft YaHei", 10))
                delete_btn.setStyleSheet(
                    "background-color: #e74c3c; color: white; border-radius: 3px;"
                )
                delete_btn.clicked.connect(
                    lambda checked, idx=i: self.delete_image(idx)
                )
                self.delete_buttons.append(delete_btn)
                btn_layout.addWidget(delete_btn)

            v_layout.addLayout(btn_layout)
            image_layout.addLayout(v_layout)

        layout.addWidget(image_container)

        # 连接表格点击事件
        self.table.cellClicked.connect(self.on_table_row_clicked)

        # 加载数据
        self.load_data()

        return page

    def eventFilter(self, source, event):
        """事件过滤器，捕获表格的键盘事件"""
        if source == self.table and event.type() == QEvent.Type.KeyPress:
            if event.key() == Qt.Key.Key_Delete:
                self.delete_selected_row()
                return True
        return super().eventFilter(source, event)

    def delete_selected_row(self):
        """删除选中的行及对应的数据和文件"""
        try:
            # 获取选中的行
            selected_items = self.table.selectedItems()
            if not selected_items:
                QMessageBox.warning(self, "警告", "请先选择要删除的行！")
                return

            # 获取选中行的索引
            row = selected_items[0].row()
            # 获取商品编码（作为主键）
            product_info = self.table.item(row, 0).text()

            # 确认删除
            reply = QMessageBox.question(
                self,
                "确认",
                f"确定要删除商品 '{product_info}' 的信息及其图片吗？",
                QMessageBox.StandardButton.Yes | QMessageBox.StandardButton.No,
                QMessageBox.StandardButton.No,
            )
            if reply != QMessageBox.StandardButton.Yes:
                return

            # 连接数据库
            conn = sqlite3.connect('medicine.db')
            cursor = conn.cursor()

            # 查询要删除的记录的文件夹路径
            cursor.execute(
                "SELECT folder_path FROM medicine WHERE product_info = ?",
                (product_info,),
            )
            result = cursor.fetchone()
            folder_path = result[0] if result else None

            # 删除数据库记录
            cursor.execute(
                "DELETE FROM medicine WHERE product_info = ?", (product_info,)
            )
            conn.commit()
            conn.close()

            # 删除图片文件夹及内容
            if folder_path and os.path.exists(folder_path):
                shutil.rmtree(folder_path)

            # 从表格中删除行
            self.table.removeRow(row)

            QMessageBox.information(self, "成功", "数据和图片已成功删除！")
        except Exception as e:
            QMessageBox.critical(self, "错误", f"删除失败: {str(e)}")

    def on_cell_changed(self, row, column):
        """单元格内容变化时触发，同步更新数据库"""
        try:
            # 获取修改后的值
            new_value = self.table.item(row, column).text()
            # 获取对应行的商品编码（作为主键）
            product_info = self.table.item(row, 0).text()

            # 确定修改的字段名
            headers = [
                "product_info",
                "generic_name",
                "specification",
                "manufacturer",
                "category",
            ]
            field_name = headers[column]

            # 禁止修改商品编码(主键)
            if field_name == "product_info":
                QMessageBox.warning(self, "警告", "商品编码不能修改！")
                # 恢复原始值
                self.table.item(row, column).setText(product_info)
                return

            # 连接数据库并更新
            conn = sqlite3.connect('medicine.db')
            cursor = conn.cursor()

            # 使用参数化查询防止SQL注入
            query = f"UPDATE medicine SET {field_name} = ? WHERE product_info = ?"
            cursor.execute(query, (new_value, product_info))
            conn.commit()
            conn.close()

            QMessageBox.information(self, "成功", "数据已成功更新到数据库！")
        except Exception as e:
            QMessageBox.critical(self, "错误", f"更新数据库失败: {str(e)}")

    def delete_image(self, index):
        """删除指定索引的图片"""
        try:
            # 检查是否有选中的行
            selected_items = self.table.selectedItems()
            if not selected_items:
                QMessageBox.warning(self, "警告", "请先选择药品信息！")
                return

            # 获取选中行的商品编码和通用名
            row = selected_items[0].row()
            product_info = self.table.item(row, 0).text()
            generic_name = self.table.item(row, 1).text()

            # 连接数据库查询文件夹路径
            conn = sqlite3.connect('medicine.db')
            cursor = conn.cursor()
            cursor.execute(
                "SELECT folder_path, main_image_path FROM medicine WHERE product_info = ?",
                (product_info,),
            )
            result = cursor.fetchone()
            conn.close()

            if not result:
                QMessageBox.warning(self, "警告", "未找到该药品的文件夹路径！")
                return

            folder_path, main_image_path = result

            # 确保文件夹存在
            if not os.path.exists(folder_path):
                QMessageBox.warning(self, "警告", f"文件夹不存在：{folder_path}")
                return

            # 获取文件夹中的所有图片文件
            image_extensions = ['.png', '.jpg', '.jpeg', '.bmp', '.gif']
            image_files = []
            for file in os.listdir(folder_path):
                ext = os.path.splitext(file)[1].lower()
                if ext in image_extensions:
                    image_files.append(os.path.join(folder_path, file))

            # 确保主图在第一个位置
            if main_image_path and os.path.exists(main_image_path):
                if main_image_path in image_files:
                    image_files.remove(main_image_path)
                image_files.insert(0, main_image_path)

            # 检查索引是否有效
            if index >= len(image_files):
                QMessageBox.warning(self, "警告", "无效的图片索引！")
                return

            # 确认删除，显示序列信息
            sequence = index + 1 if index > 0 else 1
            reply = QMessageBox.question(
                self,
                "确认",
                f"确定要删除序列{sequence}的图片吗？",
                QMessageBox.StandardButton.Yes | QMessageBox.StandardButton.No,
                QMessageBox.StandardButton.No,
            )
            if reply != QMessageBox.StandardButton.Yes:
                return

            # 获取要删除的图片路径
            image_path = image_files[index]

            # 如果删除的是主图，需要更新数据库
            is_main_image = index == 0

            if is_main_image:
                # 如果还有其他图片，将第一张非主图设为主图并更新命名
                if len(image_files) > 1:
                    new_main_image_path = image_files[1]
                    # 重命名新主图为正确格式: 商品编码+通用名+main
                    clean_generic_name = self.clean_filename(generic_name)
                    _, ext = os.path.splitext(new_main_image_path)
                    main_filename = f"{product_info}_{clean_generic_name}_main{ext}"
                    new_main_path = os.path.join(folder_path, main_filename)
                    try:
                        os.rename(new_main_image_path, new_main_path)
                        new_main_image_path = new_main_path
                    except Exception as e:
                        QMessageBox.warning(self, "警告", f"更新主图名称失败: {str(e)}")
                else:
                    new_main_image_path = ''

                # 更新数据库
                conn = sqlite3.connect('medicine.db')
                cursor = conn.cursor()
                cursor.execute(
                    "UPDATE medicine SET main_image_path = ? WHERE product_info = ?",
                    (new_main_image_path, product_info),
                )
                conn.commit()
                conn.close()

            # 删除图片文件
            try:
                os.remove(image_path)
            except Exception as e:
                QMessageBox.critical(self, "错误", f"删除图片文件失败: {str(e)}")
                return

            # 如果删除的是非主图，更新后续图片的序列编号
            if not is_main_image:
                # 获取剩余图片文件
                remaining_images = []
                for file in os.listdir(folder_path):
                    ext = os.path.splitext(file)[1].lower()
                    if ext in image_extensions:
                        remaining_images.append(os.path.join(folder_path, file))

                # 确保主图在首位
                if main_image_path and os.path.exists(main_image_path):
                    if main_image_path in remaining_images:
                        remaining_images.remove(main_image_path)
                    remaining_images.insert(0, main_image_path)

                # 重新编号从删除位置之后的图片
                # 先筛选出非主图
                non_main_remaining = [
                    img for img in remaining_images if img != main_image_path
                ]

                # 按当前序列编号排序
                def get_sequence_number(file_path):
                    try:
                        filename = os.path.basename(file_path)
                        name_parts_ = filename.split('_')
                        if len(name_parts_) >= 3:
                            sequence_part = name_parts_[-1].split('.')[0]
                            return int(sequence_part)
                    except:
                        pass
                    return 0

                non_main_remaining.sort(key=get_sequence_number)

                # 重新编号非主图
                for i, old_path in enumerate(non_main_remaining):
                    # 新序列编号从1开始
                    new_sequence = i + 1

                    old_filename = os.path.basename(old_path)
                    name_parts = old_filename.split('_')
                    if len(name_parts) >= 3:
                        product_code = name_parts[0]
                        generic_name_part = '_'.join(name_parts[1:-1])
                        _, ext = os.path.splitext(old_filename)

                        new_filename = (
                            f"{product_code}_{generic_name_part}_{new_sequence}{ext}"
                        )
                        new_path = os.path.join(folder_path, new_filename)

                        # 重命名文件
                        try:
                            os.rename(old_path, new_path)
                        except Exception as e:
                            QMessageBox.warning(
                                self, "警告", f"更新图片序列失败: {str(e)}"
                            )
                            continue

            # 刷新图片显示
            self.on_table_row_clicked(row, 0)

            QMessageBox.information(self, "成功", "图片已成功删除！")
        except Exception as e:
            QMessageBox.critical(self, "错误", f"删除图片失败: {str(e)}")

    def replace_image(self, index):
        """更换指定索引的图片"""
        try:
            # 检查是否有选中的行
            selected_items = self.table.selectedItems()
            if not selected_items:
                QMessageBox.warning(self, "警告", "请先选择药品信息！")
                return

            # 获取选中行的商品编码和通用名
            row = selected_items[0].row()
            product_info = self.table.item(row, 0).text()
            generic_name = self.table.item(row, 1).text()

            # 连接数据库查询文件夹路径
            conn = sqlite3.connect('medicine.db')
            cursor = conn.cursor()
            cursor.execute(
                "SELECT folder_path, main_image_path FROM medicine WHERE product_info = ?",
                (product_info,),
            )
            result = cursor.fetchone()
            conn.close()

            if not result:
                QMessageBox.warning(self, "警告", "未找到该药品的文件夹路径！")
                return

            folder_path, main_image_path = result

            # 确保文件夹存在
            if not os.path.exists(folder_path):
                QMessageBox.warning(self, "警告", f"文件夹不存在：{folder_path}")
                return

            # 打开文件对话框选择新图片
            file_path, _ = QFileDialog.getOpenFileName(
                self, "选择图片", "", "图片文件 (*.png *.jpg *.jpeg *.bmp *.gif)"
            )

            if not file_path:
                return

            # 确定要替换的图片路径
            if index == 0:
                # 主图使用固定命名格式: 商品编码+通用名+main
                clean_generic_name = self.clean_filename(generic_name)
                _, ext = os.path.splitext(file_path)
                main_filename = f"{product_info}_{clean_generic_name}_main{ext}"
                target_path = os.path.join(folder_path, main_filename)
            else:
                # 获取文件夹中的所有图片文件
                image_extensions = ['.png', '.jpg', '.jpeg', '.bmp', '.gif']
                image_files = []
                for file in os.listdir(folder_path):
                    ext = os.path.splitext(file)[1].lower()
                    if ext in image_extensions:
                        image_files.append(os.path.join(folder_path, file))

                # 确保主图在第一个位置
                if main_image_path and os.path.exists(main_image_path):
                    if main_image_path in image_files:
                        image_files.remove(main_image_path)
                    image_files.insert(0, main_image_path)

                # 检查索引是否有效
                if index >= len(image_files):
                    QMessageBox.warning(self, "警告", "无效的图片索引！")
                    return

                target_path = image_files[index]

            # 复制新图片到目标路径，覆盖原有图片
            shutil.copy2(file_path, target_path)

            # 如果替换的是主图，更新数据库
            if index == 0:
                conn = sqlite3.connect('medicine.db')
                cursor = conn.cursor()
                cursor.execute(
                    "UPDATE medicine SET main_image_path = ? WHERE product_info = ?",
                    (target_path, product_info),
                )
                conn.commit()
                conn.close()

            # 替换非主图逻辑已在else分支处理

            # 刷新图片显示
            self.on_table_row_clicked(row, 0)

            QMessageBox.information(self, "成功", "图片已成功更换！")
        except Exception as e:
            QMessageBox.critical(self, "错误", f"更换图片失败: {str(e)}")

    @staticmethod
    def clean_filename(filename):
        """清理文件名中的无效字符"""
        # 替换Windows文件名中不允许的字符
        return re.sub(r'[\\/:*?\"<>|]', ' ', filename)

    def add_image(self, index):
        """添加新图片"""
        try:
            # 检查是否为主图位置
            if index == 0:
                QMessageBox.warning(self, "警告", "主图位置不能添加图片，只能更换！")
                return

            # 检查是否有选中的行
            selected_items = self.table.selectedItems()
            if not selected_items:
                QMessageBox.warning(self, "警告", "请先选择药品信息！")
                return

            # 获取选中行的商品编码和通用名
            row = selected_items[0].row()
            product_info = self.table.item(row, 0).text()
            generic_name = self.table.item(row, 1).text()

            # 连接数据库查询文件夹路径
            conn = sqlite3.connect('medicine.db')
            cursor = conn.cursor()
            cursor.execute(
                "SELECT folder_path, main_image_path FROM medicine WHERE product_info = ?",
                (product_info,),
            )
            result = cursor.fetchone()
            conn.close()

            if not result:
                QMessageBox.warning(self, "警告", "未找到该药品的文件夹路径！")
                return

            folder_path, main_image_path = result

            # 确保文件夹存在
            if not os.path.exists(folder_path):
                QMessageBox.warning(self, "警告", f"文件夹不存在：{folder_path}")
                return

            # 获取文件夹中的所有图片文件
            image_extensions = ['.png', '.jpg', '.jpeg', '.bmp', '.gif']
            image_files = []
            for file in os.listdir(folder_path):
                ext = os.path.splitext(file)[1].lower()
                if ext in image_extensions:
                    image_files.append(os.path.join(folder_path, file))

            # 确保主图在列表中
            if (
                main_image_path
                and os.path.exists(main_image_path)
                and main_image_path not in image_files
            ):
                image_files.append(main_image_path)

            # 按序列编号排序（去除主图后）
            non_main_images = [f for f in image_files if f != main_image_path]

            # 尝试按文件名中的序列编号排序
            def get_sequence_number(file_path_):
                try:
                    filename = os.path.basename(file_path_)
                    name_parts = filename.split('_')
                    if len(name_parts) >= 3:
                        # 提取最后一部分作为序列编号
                        sequence_part = name_parts[-1].split('.')[0]
                        # 检查是否为主图标记
                        if sequence_part.lower() == 'main':
                            return 0  # 主图序列为0
                        return int(sequence_part)
                except:
                    pass
                return 0

            non_main_images.sort(key=get_sequence_number)

            # 重新构建图片列表，主图在首位
            sorted_image_files = []
            if main_image_path and os.path.exists(main_image_path):
                sorted_image_files.append(main_image_path)
            sorted_image_files.extend(non_main_images)

            # 检查图片数量是否已达到6张
            if len(sorted_image_files) >= 6:
                QMessageBox.warning(self, "警告", "每个药品最多只能有6张图片！")
                return

            # 打开文件对话框选择新图片
            file_path, _ = QFileDialog.getOpenFileName(
                self, "选择图片", "", "图片文件 (*.png *.jpg *.jpeg *.bmp *.gif)"
            )

            if not file_path:
                return

            # 生成新文件名：商品编码+通用名+序列
            clean_generic_name = self.clean_filename(generic_name)
            # 非主图序号从1开始，基于当前非主图的数量
            serial_number = len(non_main_images) + 1
            _, ext = os.path.splitext(file_path)
            new_filename = f"{product_info}_{clean_generic_name}_{serial_number}{ext}"
            target_path = os.path.join(folder_path, new_filename)

            # 检查目标路径是否已存在
            if os.path.exists(target_path):
                reply = QMessageBox.question(
                    self,
                    "确认",
                    f"序列{serial_number}的图片已存在，是否替换？",
                    QMessageBox.StandardButton.Yes | QMessageBox.StandardButton.No,
                )
                if reply == QMessageBox.StandardButton.No:
                    return

            # 复制新图片到目标路径
            shutil.copy2(file_path, target_path)

            # 刷新图片显示
            self.on_table_row_clicked(row, 0)

            QMessageBox.information(
                self, "成功", f"图片已成功添加到序列{serial_number}！"
            )
        except Exception as e:
            QMessageBox.critical(self, "错误", f"添加图片失败: {str(e)}")

    def on_table_row_clicked(self, row, column):
        """表格行点击事件，显示对应药品的图片"""
        try:
            # 获取选中行的商品编码
            product_info = self.table.item(row, 0).text()

            # 连接数据库查询文件夹路径
            conn = sqlite3.connect('medicine.db')
            cursor = conn.cursor()
            cursor.execute(
                "SELECT folder_path, main_image_path FROM medicine WHERE product_info = ?",
                (product_info,),
            )
            result = cursor.fetchone()
            conn.close()

            if not result:
                # 清空所有图片标签
                for label in self.image_labels:
                    label.clear()
                return

            folder_path, main_image_path = result

            # 清空所有图片标签
            for label in self.image_labels:
                label.clear()

            # 如果文件夹不存在，返回
            if not os.path.exists(folder_path):
                return

            # 获取文件夹中的所有图片文件
            image_extensions = ['.png', '.jpg', '.jpeg', '.bmp', '.gif']
            image_files = []
            for file in os.listdir(folder_path):
                ext = os.path.splitext(file)[1].lower()
                if ext in image_extensions:
                    image_files.append(os.path.join(folder_path, file))

            # 确保主图在第一个位置
            if main_image_path and os.path.exists(main_image_path):
                # 从列表中移除主图（如果存在）
                if main_image_path in image_files:
                    image_files.remove(main_image_path)
                # 将主图插入到第一个位置
                image_files.insert(0, main_image_path)

            # 加载图片到标签中，最多6张
            for i, image_path in enumerate(image_files[:6]):
                pixmap = QPixmap(image_path)
                if not pixmap.isNull():
                    # 缩放图片以适应标签大小
                    scaled_pixmap = pixmap.scaled(
                        200,
                        200,
                        Qt.AspectRatioMode.KeepAspectRatio,
                        Qt.TransformationMode.SmoothTransformation,
                    )
                    self.image_labels[i].setPixmap(scaled_pixmap)

                    # 动态设置tooltip，确保位置与名称关联
                    filename = os.path.basename(image_path)
                    if '_main' in filename.lower():
                        self.image_labels[i].setToolTip("主图 (序列1)")
                    else:
                        try:
                            name_parts = filename.split('_')
                            if len(name_parts) >= 3:
                                sequence_part = name_parts[-1].split('.')[0]
                                self.image_labels[i].setToolTip(
                                    f"图片 (序列{sequence_part})"
                                )
                        except:
                            self.image_labels[i].setToolTip(f"图片 (位置{i + 1})")
        except Exception as e:
            QMessageBox.critical(self, "错误", f"加载图片失败: {str(e)}")

    def load_data(self, search_query=""):
        """从数据库加载数据到表格"""
        try:
            # 连接数据库
            conn = sqlite3.connect('medicine.db')
            cursor = conn.cursor()

            # 查询数据
            if search_query:
                # 使用参数化查询防止SQL注入
                query = """
                        SELECT product_info, generic_name, specification, manufacturer, category
                        FROM medicine
                        WHERE product_info LIKE ? \
                           OR generic_name LIKE ? \
                           OR manufacturer LIKE ? \
                        """
                search_param = f"%{search_query}%"
                cursor.execute(query, (search_param, search_param, search_param))
            else:
                cursor.execute(
                    "SELECT product_info, generic_name, specification, manufacturer, category FROM medicine"
                )

            # 获取所有数据
            data = cursor.fetchall()

            # 设置表格行数
            self.table.setRowCount(len(data))

            # 暂时断开cellChanged信号
            self.table.cellChanged.disconnect(self.on_cell_changed)

            # 填充表格
            for row, row_data in enumerate(data):
                for col, col_data in enumerate(row_data):
                    item = QTableWidgetItem(str(col_data))
                    item.setTextAlignment(Qt.AlignmentFlag.AlignCenter)
                    self.table.setItem(row, col, item)

            # 重新连接cellChanged信号
            self.table.cellChanged.connect(self.on_cell_changed)

            # 调整列宽 - 设置为可交互模式且不影响其他列
            for col in range(self.table.columnCount()):
                self.table.horizontalHeader().setSectionResizeMode(
                    col, QHeaderView.ResizeMode.Interactive
                )

            # 确保表格可以水平滚动，避免调整一列影响其他列
            self.table.setHorizontalScrollBarPolicy(
                Qt.ScrollBarPolicy.ScrollBarAsNeeded
            )

            conn.close()
        except Exception as e:
            QMessageBox.critical(self, "错误", f"加载数据失败: {str(e)}")

    def search_data(self):
        """搜索数据"""
        search_query = self.search_edit.text()
        self.load_data(search_query)

    def create_search_page(self):
        """创建搜索页面，包含搜索框和表格"""
        page = QWidget()
        layout = QVBoxLayout(page)
        layout.setContentsMargins(25, 25, 25, 25)
        layout.setSpacing(20)

        # 创建搜索区域
        search_layout = QHBoxLayout()
        self.search_edit_search = QLineEdit()
        self.search_edit_search.setFont(QFont("Microsoft YaHei", 12))
        self.search_edit_search.setPlaceholderText("输入商品编码、通用名或规格...")
        self.search_edit_search.setMaximumWidth(300)  # 约35个字符宽度
        search_btn = QPushButton("搜索")
        search_btn.setFont(QFont("Microsoft YaHei", 12))
        search_btn.setStyleSheet(
            "background-color: #3498db; color: white; padding: 5px 15px; border-radius: 5px;"
        )
        search_btn.setFixedWidth(90)
        search_btn.clicked.connect(self.search_data_search)

        search_layout.addWidget(self.search_edit_search)
        search_layout.addWidget(search_btn)
        search_layout.setAlignment(Qt.AlignmentFlag.AlignLeft)  # 设置搜索区域靠左对齐
        layout.addLayout(search_layout)

        # 创建表格
        self.search_table = QTableWidget()
        self.search_table.setFont(QFont("Microsoft YaHei", 12))
        # 设置表头
        headers = ["商品编码", "通用名", "规格", "Pic"]
        self.search_table.setColumnCount(len(headers))
        self.search_table.setHorizontalHeaderLabels(headers)
        # 设置商品编码列宽为90px，并设置列宽模式为固定
        self.search_table.setColumnWidth(0, 90)
        self.search_table.horizontalHeader().setSectionResizeMode(
            0, QHeaderView.ResizeMode.Fixed
        )
        # 设置表格样式
        self.search_table.horizontalHeader().setStyleSheet(
            "QHeaderView::section {background-color: #f0f0f0; font-weight: bold;}"
        )
        self.search_table.setAlternatingRowColors(True)
        self.search_table.setStyleSheet("alternate-background-color: #f9f9f9;")
        # 设置整行选择模式
        self.search_table.setSelectionBehavior(
            QTableWidget.SelectionBehavior.SelectRows
        )
        self.search_table.setSelectionMode(QTableWidget.SelectionMode.SingleSelection)
        # 禁止编辑
        self.search_table.setEditTriggers(QTableWidget.EditTrigger.NoEditTriggers)
        # 设置选中行样式
        self.search_table.setStyleSheet(
            """
            alternate-background-color: #f9f9f9;
            QTableWidget::item:selected {
                background-color: #3498db;
                color: white;
            }
        """
        )

        # 创建表格和图片显示区域的水平布局
        table_image_layout = QHBoxLayout()
        table_image_layout.setSpacing(20)

        # 添加表格到水平布局
        table_image_layout.addWidget(self.search_table, 1)

        # 创建图片显示区域
        image_layout = QVBoxLayout()

        self.image_label = QLabel("点击左侧表格行显示图片")
        self.image_label.setAlignment(Qt.AlignmentFlag.AlignCenter)
        self.image_label.setMinimumSize(560, 300)  # 稍微小于容器宽度，留出边距
        self.image_label.setStyleSheet("border: 1px solid #ddd;")
        image_layout.addWidget(self.image_label)

        # 添加6个横向排列的空白图片标签
        blank_images_layout = QHBoxLayout()
        blank_images_layout.setSpacing(10)  # 设置标签间距

        # 创建6个空白图片标签
        self.blank_image_labels = []
        for i in range(6):
            blank_label = QLabel(f"空白图片 {i + 1}")
            blank_label.setAlignment(Qt.AlignmentFlag.AlignCenter)
            blank_label.setMinimumSize(100, 100)  # 设置最小大小为正方形
            blank_label.setMaximumSize(100, 100)  # 设置最大大小为正方形
            blank_label.setStyleSheet(
                "border: 1px dashed #aaa; background-color: #f5f5f5;"
            )
            # 为标签添加点击事件
            blank_label.mousePressEvent = (
                lambda event, idx=i: self.on_blank_image_clicked(idx)
            )
            self.blank_image_labels.append(blank_label)
            blank_images_layout.addWidget(blank_label)

        # 将水平布局添加到主布局
        image_layout.addLayout(blank_images_layout)

        # 添加保存按钮
        save_btn = QPushButton("保存")
        save_btn.setFont(QFont("Microsoft YaHei", 12))
        save_btn.setStyleSheet(
            "background-color: #2ecc71; color: white; padding: 5px 15px; border-radius: 5px;"
        )
        save_btn.clicked.connect(self.save_current_image)
        image_layout.addWidget(save_btn, alignment=Qt.AlignmentFlag.AlignCenter)

        table_image_layout.addLayout(image_layout, 1)  # 直接添加布局，保持原有功能

        # 添加水平布局到主布局
        layout.addLayout(table_image_layout)

        # 连接表格点击事件
        self.search_table.itemClicked.connect(self.on_search_table_item_clicked)

        # 初始加载数据
        self.load_search_data()

        return page

    def on_search_table_item_clicked(self, item):
        """处理搜索表格行点击事件，显示对应商品的主图"""
        # 获取点击行的商品编码
        row = item.row()
        product_code = self.search_table.item(row, 0).text()
        self.display_product_image(product_code)

    def on_blank_image_clicked(self, index):
        """处理小图片标签点击事件，在大图区域显示对应的图片"""
        try:
            clicked_label = self.blank_image_labels[index]
            # 获取存储的图片路径
            image_path = clicked_label.toolTip()

            if image_path and os.path.exists(image_path):
                # 重置所有标签的当前状态
                for label in self.blank_image_labels:
                    setattr(label, 'is_current', False)
                # 设置当前标签为活动状态
                setattr(clicked_label, 'is_current', True)
                # 重新加载原始图片
                pixmap = QPixmap()
                if pixmap.load(image_path, "", Qt.ImageConversionFlag.AutoColor):
                    # 高质量缩放
                    scaled_pixmap = pixmap.scaled(
                        self.image_label.size(),
                        Qt.AspectRatioMode.KeepAspectRatio,
                        Qt.TransformationMode.SmoothTransformation,
                    )
                    self.image_label.setPixmap(scaled_pixmap)
        except Exception as e:
            print(f"切换图片错误: {str(e)}")
            self.image_label.setText("切换图片失败")

    def save_current_image(self):
        """保存当前大图预览区显示的图片到本地"""
        try:
            # 检查是否有图片显示
            if not self.image_label.pixmap():
                QMessageBox.information(self, "提示", "没有图片可保存")
                return

            # 获取当前显示的图片路径
            # 遍历所有小图片标签查找当前显示的图片
            current_image_path = None
            for label in self.blank_image_labels:
                if hasattr(label, 'is_current') and label.is_current:
                    current_image_path = label.toolTip()
                    break

            # 如果找不到路径，使用文件对话框让用户选择保存位置
            if not current_image_path or not os.path.exists(current_image_path):
                # 获取默认保存文件名
                default_filename = "product_image.png"
                if current_image_path:
                    default_filename = os.path.basename(current_image_path)

                # 打开保存文件对话框
                save_path, _ = QFileDialog.getSaveFileName(
                    self,
                    "保存图片",
                    os.path.join(os.path.expanduser("~"), "Pictures", default_filename),
                    "图片文件 (*.png *.jpg *.jpeg *.bmp);;所有文件 (*)",
                )

                if save_path:
                    # 保存图片
                    self.image_label.pixmap().save(save_path)
                    QMessageBox.information(self, "成功", f"图片已保存到: {save_path}")
            else:
                # 使用原始图片路径保存
                # 获取文件名
                filename = os.path.basename(current_image_path)
                # 打开保存文件对话框，默认使用原始文件名
                save_path, _ = QFileDialog.getSaveFileName(
                    self,
                    "保存图片",
                    os.path.join(os.path.expanduser("~"), "Pictures", filename),
                    "图片文件 (*.png *.jpg *.jpeg *.bmp);;所有文件 (*)",
                )

                if save_path:
                    # 复制文件
                    shutil.copy2(current_image_path, save_path)
                    QMessageBox.information(self, "成功", f"图片已保存到: {save_path}")
        except Exception as e:
            print(f"保存图片错误: {str(e)}")
            QMessageBox.critical(self, "错误", f"保存图片失败: {str(e)}")

    def display_product_image(self, product_code):
        """根据商品编码显示对应的图片，第一个标签显示主图(_main)"""
        try:
            # 查询数据库获取文件夹路径
            conn = sqlite3.connect('medicine.db')
            cursor = conn.cursor()
            cursor.execute(
                "SELECT folder_path FROM medicine WHERE product_info = ?",
                (product_code,),
            )
            result = cursor.fetchone()
            conn.close()

            # 重置所有图片标签
            self.image_label.clear()
            self.image_label.setText("点击左侧表格行显示图片")
            for label in self.blank_image_labels:
                label.clear()
                label.setText(f"空白图片 {self.blank_image_labels.index(label) + 1}")

            if result and result[0]:
                folder_path = result[0]
                if os.path.exists(folder_path):
                    # 获取文件夹中的所有图片
                    image_extensions = ['.jpg', '.jpeg', '.png', '.gif', '.bmp']
                    image_files = [
                        f
                        for f in os.listdir(folder_path)
                        if os.path.splitext(f)[1].lower() in image_extensions
                    ]

                    # 重置所有标签的当前状态
                    for label in self.blank_image_labels:
                        setattr(label, 'is_current', False)

                    if image_files:
                        # 初始化变量
                        main_image = None
                        other_images = []

                        # 区分主图和其他图片
                        for image_file in image_files:
                            if '_main' in image_file.lower():
                                main_image = image_file
                            else:
                                other_images.append(image_file)

                        # 如果没有找到主图，使用第一张图片
                        if not main_image and image_files:
                            main_image = image_files[0]
                            other_images = image_files[1:]

                        # 显示主图在第一个标签（最左边）和大图
                        if main_image:
                            main_image_path = os.path.join(folder_path, main_image)
                            if os.path.exists(main_image_path):
                                # 加载主图到第一个标签（最左边）
                                main_label = self.blank_image_labels[0]
                                pixmap = QPixmap()
                                if pixmap.load(
                                    main_image_path,
                                    "",
                                    Qt.ImageConversionFlag.AutoColor,
                                ):
                                    scaled_pixmap = pixmap.scaled(
                                        100,
                                        100,
                                        Qt.AspectRatioMode.KeepAspectRatio,
                                        Qt.TransformationMode.SmoothTransformation,
                                    )
                                    main_label.setPixmap(scaled_pixmap)
                                    main_label.setText("")
                                    main_label.setToolTip(main_image_path)
                                    setattr(main_label, 'is_current', True)

                                # 加载主图到大图
                                big_pixmap = QPixmap()
                                if big_pixmap.load(
                                    main_image_path,
                                    "",
                                    Qt.ImageConversionFlag.AutoColor,
                                ):
                                    # 统一使用self.image_label作为大图组件
                                    if hasattr(self, 'image_label'):
                                        self.image_label.setPixmap(
                                            big_pixmap.scaled(
                                                self.image_label.size(),
                                                Qt.AspectRatioMode.KeepAspectRatio,
                                                Qt.TransformationMode.SmoothTransformation,
                                            )
                                        )
                                        self.image_label.setToolTip(main_image_path)

                        # 显示其他图片在剩余标签（从索引1开始）
                        image_index = 1
                        for image_file in other_images:
                            if image_index < len(self.blank_image_labels):
                                image_path = os.path.join(folder_path, image_file)
                                if os.path.exists(image_path):
                                    label = self.blank_image_labels[image_index]
                                    pixmap = QPixmap()
                                    if pixmap.load(
                                        image_path, "", Qt.ImageConversionFlag.AutoColor
                                    ):
                                        scaled_pixmap = pixmap.scaled(
                                            100,
                                            100,
                                            Qt.AspectRatioMode.KeepAspectRatio,
                                            Qt.TransformationMode.SmoothTransformation,
                                        )
                                        label.setPixmap(scaled_pixmap)
                                        label.setText("")
                                        label.setToolTip(image_path)
                                image_index += 1
                            else:
                                break

                        # 填充剩余标签（如果有）
                        while image_index < len(self.blank_image_labels):
                            self.blank_image_labels[image_index].clear()
                            self.blank_image_labels[image_index].setText("")
                            image_index += 1
                    else:
                        # 没有图片时清空所有标签
                        for label in self.blank_image_labels:
                            label.clear()
                            label.setText("")
                        if hasattr(self, 'image_label'):
                            self.image_label.setText("暂无图片")
            else:
                # 如果没有找到文件夹，显示默认文本
                self.image_label.setText("暂无图片")
        except Exception as e:
            print(f"显示图片错误: {str(e)}")
            self.image_label.setText("加载图片失败")
            for label in self.blank_image_labels:
                label.setText("加载失败")

    def load_search_data(self, search_query=""):
        """加载搜索页面的数据到表格"""
        try:
            # 连接数据库
            conn = sqlite3.connect('medicine.db')
            cursor = conn.cursor()

            # 查询数据
            if search_query:
                # 使用参数化查询防止SQL注入
                query = """
                        SELECT product_info, generic_name, specification, folder_path
                        FROM medicine
                        WHERE product_info LIKE ? \
                           OR generic_name LIKE ? \
                           OR specification LIKE ? \
                        """
                search_param = f"%{search_query}%"
                cursor.execute(query, (search_param, search_param, search_param))
            else:
                cursor.execute(
                    "SELECT product_info, generic_name, specification, folder_path FROM medicine"
                )

            # 获取所有数据
            data = cursor.fetchall()

            # 设置表格行数
            self.search_table.setRowCount(len(data))

            # 填充表格
            for row, row_data in enumerate(data):
                # 商品编码
                item_code = QTableWidgetItem(str(row_data[0]))
                item_code.setTextAlignment(Qt.AlignmentFlag.AlignCenter)
                self.search_table.setItem(row, 0, item_code)

                # 通用名
                item_name = QTableWidgetItem(str(row_data[1]))
                item_name.setTextAlignment(Qt.AlignmentFlag.AlignCenter)
                self.search_table.setItem(row, 1, item_name)

                # 规格
                item_spec = QTableWidgetItem(str(row_data[2]))
                item_spec.setTextAlignment(Qt.AlignmentFlag.AlignCenter)
                self.search_table.setItem(row, 2, item_spec)

                # 图片列 - 显示图片数量
                folder_path = row_data[3]
                image_count = 0
                if folder_path and os.path.exists(folder_path):
                    image_extensions = ['.jpg', '.jpeg', '.png', '.gif', '.bmp']
                    image_files = [
                        f
                        for f in os.listdir(folder_path)
                        if os.path.splitext(f)[1].lower() in image_extensions
                    ]
                    image_count = len(image_files)

                item_pic = QTableWidgetItem(str(image_count))
                item_pic.setTextAlignment(Qt.AlignmentFlag.AlignCenter)
                self.search_table.setItem(row, 3, item_pic)

            # 调整列宽
            self.search_table.horizontalHeader().setSectionResizeMode(
                QHeaderView.ResizeMode.Stretch
            )

            # 关闭数据库连接
            conn.close()
        except Exception as e:
            print(f"加载搜索数据错误: {str(e)}")
            QMessageBox.critical(self, "错误", f"加载数据失败: {str(e)}")

    def search_data_search(self):
        """搜索页面的搜索功能"""
        search_query = self.search_edit_search.text()
        self.load_search_data(search_query)

    def get_image_count(self, product_code):
        """获取指定商品编码对应的图片数量"""
        try:
            # 查询数据库获取文件夹路径
            conn = sqlite3.connect('medicine.db')
            cursor = conn.cursor()
            cursor.execute(
                "SELECT folder_path FROM medicine WHERE product_info = ?",
                (product_code,),
            )
            result = cursor.fetchone()
            conn.close()

            if result and result[0]:
                folder_path = result[0]
                if os.path.exists(folder_path):
                    # 统计文件夹中的图片数量
                    image_extensions = ['.jpg', '.jpeg', '.png', '.gif', '.bmp']
                    return len(
                        [
                            f
                            for f in os.listdir(folder_path)
                            if os.path.splitext(f)[1].lower() in image_extensions
                        ]
                    )
            return 0
        except Exception as e:
            print(f"获取图片数量错误: {str(e)}")
            return 0

    def create_settings_page(self):
        """创建设置页面"""
        page = QWidget()
        layout = QVBoxLayout(page)
        layout.setContentsMargins(25, 25, 25, 25)
        layout.setSpacing(20)

        # 添加标题
        title_label = QLabel("系统设置")
        title_label.setFont(QFont("Microsoft YaHei", 24))
        title_label.setAlignment(Qt.AlignmentFlag.AlignCenter)
        layout.addWidget(title_label)

        # 创建表单区域
        form_group = QGroupBox("路径设置")
        form_group.setFont(QFont("Microsoft YaHei", 14))
        form_layout = QFormLayout(form_group)
        form_layout.setSpacing(15)

        # 创建路径输入框和浏览按钮
        path_layout = QHBoxLayout()
        self.path_edit = QLineEdit(self.save_path)
        self.path_edit.setFont(QFont("Microsoft YaHei", 12))
        browse_btn = QPushButton("浏览...")
        browse_btn.setFont(QFont("Microsoft YaHei", 12))
        browse_btn.clicked.connect(self.browse_path)

        path_layout.addWidget(self.path_edit)
        path_layout.addWidget(browse_btn)

        # 添加到表单
        form_layout.addRow("图片保存路径:", path_layout)

        # 添加表单到布局
        layout.addWidget(form_group)

        # 创建按钮区域
        btn_layout = QHBoxLayout()

        # 保存按钮
        save_btn = QPushButton("保存设置")
        save_btn.setFont(QFont("Microsoft YaHei", 14))
        save_btn.setStyleSheet(
            "background-color: #3498db; color: white; padding: 10px 20px; border-radius: 5px;"
        )
        save_btn.clicked.connect(self.save_settings)

        # 添加按钮到布局
        btn_layout.addWidget(save_btn)

        # 添加按钮布局到主布局
        layout.addLayout(btn_layout)

        return page

    def browse_path(self):
        """浏览文件夹路径"""
        path = QFileDialog.getExistingDirectory(self, "选择保存路径", self.save_path)
        if path:
            self.path_edit.setText(path)

    def save_settings(self):
        """保存设置"""
        new_path = self.path_edit.text()
        if not new_path:
            QMessageBox.warning(self, "警告", "保存路径不能为空！")
            return

        # 验证路径是否存在
        if not os.path.exists(new_path):
            try:
                os.makedirs(new_path)
            except Exception as e:
                QMessageBox.critical(self, "错误", f"创建路径失败: {str(e)}")
                return

        # 保存设置
        self.save_path = new_path
        self.settings.setValue('save_path', new_path)
        QMessageBox.information(self, "成功", "设置保存成功！")

    def create_upload_page(self):
        """创建上传页面，包含信息录入和图片上传功能"""
        page = QWidget()
        layout = QVBoxLayout(page)
        layout.setContentsMargins(25, 25, 25, 25)
        layout.setSpacing(20)

        # 创建表单区域
        form_group = QGroupBox("")
        form_group.setFont(QFont("Microsoft YaHei", 14))
        form_layout = QFormLayout(form_group)
        form_layout.setSpacing(15)

        # 创建输入字段
        self.product_info_edit = QLineEdit()
        self.generic_name_edit = QLineEdit()
        self.specification_edit = QLineEdit()
        self.manufacturer_edit = QLineEdit()
        self.barcode_edit = QLineEdit()

        # 创建分类下拉菜单
        self.category_combo = QComboBox()
        self.category_combo.addItems(["无", "RX", "OTC", "医疗器械", "中药饮片"])

        # 添加字段到表单
        form_layout.addRow("商品信息:", self.product_info_edit)
        form_layout.addRow("通用名:", self.generic_name_edit)
        form_layout.addRow("规格:", self.specification_edit)
        form_layout.addRow("生产厂家:", self.manufacturer_edit)
        form_layout.addRow("条形码:", self.barcode_edit)
        form_layout.addRow("分类:", self.category_combo)

        # 添加粘贴按钮
        paste_layout = QHBoxLayout()
        paste_btn = QPushButton("从Excel粘贴数据")
        paste_btn.setFont(QFont("Microsoft YaHei", 12))
        paste_btn.setStyleSheet(
            "background-color: #e74c3c; color: white; padding: 8px 16px; border-radius: 5px;"
        )
        paste_btn.clicked.connect(self.paste_from_excel)
        paste_layout.addWidget(paste_btn)
        form_layout.addRow(paste_layout)

        # 添加表单到布局
        layout.addWidget(form_group)

        # 创建图片上传区域
        image_group = QGroupBox("图片上传")
        image_group.setFont(QFont("Microsoft YaHei", 14))
        image_layout = QVBoxLayout(image_group)

        # 上传按钮
        upload_btn = QPushButton("上传图片")
        upload_btn.setFont(QFont("Microsoft YaHei", 12))
        upload_btn.setStyleSheet(
            "background-color: #2ecc71; color: white; padding: 8px 16px; border-radius: 5px;"
        )
        upload_btn.clicked.connect(self.upload_images)

        # 图片列表
        self.image_list = QListWidget()
        self.image_list.setIconSize(QSize(100, 100))
        self.image_list.setFont(QFont("Microsoft YaHei", 12))

        # 添加组件到布局
        image_layout.addWidget(upload_btn)
        image_layout.addWidget(self.image_list)

        # 添加图片区域到主布局
        layout.addWidget(image_group)

        # 创建按钮区域
        btn_layout = QHBoxLayout()

        # 保存按钮
        self.save_btn = QPushButton("保存信息和图片")
        self.save_btn.setFont(QFont("Microsoft YaHei", 14))
        self.save_btn.setStyleSheet(
            "background-color: #3498db; color: white; padding: 10px 20px; border-radius: 5px;"
        )
        self.save_btn.clicked.connect(self.save_medicine_info)

        # 重置按钮
        self.reset_btn = QPushButton("重置")
        self.reset_btn.setFont(QFont("Microsoft YaHei", 14))
        self.reset_btn.setStyleSheet(
            "background-color: #95a5a6; color: white; padding: 10px 20px; border-radius: 5px;"
        )
        self.reset_btn.clicked.connect(self.reset_form)

        # 添加按钮到布局
        btn_layout.addWidget(self.save_btn)
        btn_layout.addWidget(self.reset_btn)

        # 添加按钮布局到主布局
        layout.addLayout(btn_layout)

        return page

    def upload_images(self):
        """上传图片"""
        # 检查是否已达到最大上传数量
        if len(self.images) >= 6:
            QMessageBox.warning(self, "警告", "最多只能上传6张图片！")
            return

        # 打开文件对话框
        file_paths, _ = QFileDialog.getOpenFileNames(
            self, "选择图片", "", "图片文件 (*.png *.jpg *.jpeg *.bmp *.gif)"
        )

        # 过滤并添加图片
        for file_path in file_paths:
            if len(self.images) >= 6:
                QMessageBox.warning(self, "警告", "最多只能上传6张图片！")
                break

            self.images.append(file_path)

            # 创建列表项
            item = QListWidgetItem()
            item.setText(os.path.basename(file_path))

            # 显示缩略图
            pixmap = QPixmap(file_path)
            if not pixmap.isNull():
                item.setIcon(
                    QIcon(pixmap.scaled(100, 100, Qt.AspectRatioMode.KeepAspectRatio))
                )

            # 添加复选框用于设置主图
            checkbox = QCheckBox("主图")
            checkbox.setChecked(len(self.images) == 1)
            if len(self.images) == 1:
                self.main_image_index = 0

            checkbox.stateChanged.connect(
                lambda state, idx=len(self.images) - 1: self.set_main_image(state, idx)
            )

            self.image_list.addItem(item)
            self.image_list.setItemWidget(item, checkbox)

    def set_main_image(self, state, index):
        """设置主图"""
        if state == Qt.CheckState.Checked:
            # 取消其他选中状态
            for i in range(self.image_list.count()):
                if i != index:
                    item = self.image_list.item(i)
                    checkbox = self.image_list.itemWidget(item)
                    checkbox.setChecked(False)

            self.main_image_index = index
        else:
            # 如果取消主图，不设置新的主图
            if self.main_image_index == index:
                self.main_image_index = -1

    def save_medicine_info(self):
        """保存药品信息和图片到数据库和指定路径"""
        # 获取表单数据
        product_info = self.product_info_edit.text()
        generic_name = self.generic_name_edit.text()
        specification = self.specification_edit.text()
        manufacturer = self.manufacturer_edit.text()
        barcode = self.barcode_edit.text()
        category = self.category_combo.currentText()

        # 验证数据
        if not product_info or not generic_name or not manufacturer:
            QMessageBox.warning(self, "警告", "商品信息、通用名和生产厂家不能为空！")
            return

        # 如果没有上传图片，提示用户
        if not self.images:
            reply = QMessageBox.question(
                self,
                "提示",
                "没有上传图片，是否继续保存信息？",
                QMessageBox.StandardButton.Yes | QMessageBox.StandardButton.No,
                QMessageBox.StandardButton.No,
            )
            if reply == QMessageBox.StandardButton.No:
                return

        # 如果有图片但没有设置主图，提示用户
        if self.images and self.main_image_index == -1:
            QMessageBox.warning(self, "警告", "请设置一张主图！")
            return

        try:
            # 连接数据库
            conn = sqlite3.connect('medicine.db')
            cursor = conn.cursor()

            # 创建表（如果不存在）
            cursor.execute(
                '''
                           CREATE TABLE IF NOT EXISTS medicine
                           (
                               id
                               INTEGER
                               PRIMARY
                               KEY
                               AUTOINCREMENT,
                               product_info
                               TEXT,
                               generic_name
                               TEXT,
                               specification
                               TEXT,
                               manufacturer
                               TEXT,
                               barcode
                               TEXT,
                               category
                               TEXT,
                               folder_path
                               TEXT,
                               main_image_path
                               TEXT
                           )
                           '''
            )

            # 清理输入数据，去除无效字符
            self.clean_filename(barcode)
            clean_generic_name = self.clean_filename(generic_name)
            clean_product_info = self.clean_filename(product_info)

            # 创建文件夹路径 - 使用商品编码(商品信息)+通用名
            folder_name = f"{clean_product_info}_{clean_generic_name}"
            folder_path = os.path.join(self.save_path, folder_name)

            # 如果文件夹已存在，提示用户
            if os.path.exists(folder_path) and self.images:
                reply = QMessageBox.question(
                    self,
                    "提示",
                    "该药品的文件夹已存在，是否覆盖图片？",
                    QMessageBox.StandardButton.Yes | QMessageBox.StandardButton.No,
                    QMessageBox.StandardButton.No,
                )
                if reply == QMessageBox.StandardButton.No:
                    conn.close()
                    return

            # 创建文件夹
            if self.images and not os.path.exists(folder_path):
                os.makedirs(folder_path)

            # 保存图片
            main_image_path = ""
            image_paths = []

            if self.images:
                # 使用独立计数器为非主图编号，确保从1开始连续递增
                non_main_counter = 1
                for i, image_path in enumerate(self.images):
                    # 生成文件名 - 使用商品编码(商品信息)+通用名
                    ext = os.path.splitext(image_path)[1]
                    if i == self.main_image_index:
                        # 主图使用main标记
                        file_name = (
                            f"{clean_product_info}_{clean_generic_name}_main{ext}"
                        )
                    else:
                        # 非主图使用序列编号，从1开始且连续
                        file_name = f"{clean_product_info}_{clean_generic_name}_{non_main_counter}{ext}"
                        non_main_counter += 1
                    save_path = os.path.join(folder_path, file_name)

                    # 复制图片
                    shutil.copy2(image_path, save_path)
                    image_paths.append(save_path)

                    # 记录主图路径
                    if i == self.main_image_index:
                        main_image_path = save_path

            # 插入数据
            cursor.execute(
                "INSERT INTO medicine "
                "(product_info, generic_name, specification, manufacturer, "
                "barcode, category, folder_path, main_image_path) VALUES (?, ?, ?, ?, ?, ?, ?, ?)",
                (
                    product_info,
                    generic_name,
                    specification,
                    manufacturer,
                    barcode,
                    category,
                    folder_path,
                    main_image_path,
                ),
            )

            # 提交更改
            conn.commit()
            conn.close()

            QMessageBox.information(self, "成功", "药品信息和图片保存成功！")
            self.reset_form()
        except Exception as e:
            QMessageBox.critical(self, "错误", f"保存失败: {str(e)}")

    def reset_form(self):
        """重置表单"""
        self.product_info_edit.clear()
        self.generic_name_edit.clear()
        self.specification_edit.clear()
        self.manufacturer_edit.clear()
        self.barcode_edit.clear()
        self.category_combo.setCurrentIndex(0)
        self.images = []
        self.main_image_index = -1
        self.image_list.clear()

    def paste_from_excel(self):
        """从Excel粘贴数据到表单"""
        # 获取剪贴板内容
        clipboard = QApplication.clipboard()
        text = clipboard.text()

        if not text:
            QMessageBox.warning(self, "警告", "剪贴板为空，无法粘贴数据！")
            return

        # 按行分割文本
        lines = text.split('\n')
        if not lines:
            QMessageBox.warning(self, "警告", "剪贴板内容格式不正确！")
            return

        # 获取第一行数据（假设是Excel复制的第一行）
        first_line = lines[0].strip()
        if not first_line:
            QMessageBox.warning(self, "警告", "剪贴板内容为空行！")
            return

        # 按制表符分割数据
        data = first_line.split('\t')

        # 填充到表单字段，第一列对应第一行
        if len(data) >= 1:
            self.product_info_edit.setText(data[0].strip())
        if len(data) >= 2:
            self.generic_name_edit.setText(data[1].strip())
        if len(data) >= 3:
            self.specification_edit.setText(data[2].strip())
        if len(data) >= 4:
            self.manufacturer_edit.setText(data[3].strip())
        if len(data) >= 5:
            self.barcode_edit.setText(data[4].strip())

        QMessageBox.information(
            self,
            "成功",
            "数据粘贴成功！\n\n注意：第一列对应商品信息，第二列对应通用名，以此类推。",
        )


if __name__ == '__main__':
    # 确保中文显示正常
    app = QApplication(sys.argv)
    # 设置全局字体
    font = QFont("Microsoft YaHei")
    app.setFont(font)

    window = MedicineImageManager()
    window.show()
    sys.exit(app.exec())
